﻿using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Text;

namespace PasteTimer
{
    ///// <summary>
    ///// 数据库链接字符串
    ///// </summary>
    //public class OptionConnectionConfig : IOptions<OptionConnectionConfig>
    //{
    //    public OptionConnectionConfig Value => this;
    //    /// <summary>
    //    /// 主要数据库链接字符串
    //    /// </summary>
    //    public string MainConnectionString { get; set; }
    //    /// <summary>
    //    /// 只读数据库链接字符串
    //    /// </summary>
    //    public string ReadConnectionString { get; set; }
    //}

    /// <summary>
    /// redis的链接信息
    /// </summary>
    public class RedisConfig
    {
        /// <summary>
        /// 链接名称
        /// </summary>
        public string ClientName { get; set; } = "default";

        /// <summary>
        /// 主链接
        /// </summary>
        public string MainConnection { get; set; }

        /// <summary>
        /// 前缀
        /// </summary>
        public string Prefix { get; set; } = "cache:";
    }


    /// <summary>
    /// 
    /// </summary>
    public static class ObjectExtend
    {

        /// <summary>
        /// 时间转时间戳ms
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static long ToUnixTimeMilliseconds(this DateTime dt)
        {
            //这里会有+8的时间差，是否需要缓存时区。。        
            return new DateTimeOffset(dt).ToUnixTimeMilliseconds();
        }

        /// <summary>
        /// 时间转时间戳s
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static long ToUnixTimeSeconds(this DateTime dt)
        {
            var dto = new DateTimeOffset(dt);
            //这里会有+8的时间差，是否需要缓存时区。。        
            return new DateTimeOffset(dt).ToUnixTimeSeconds();
        }

        /// <summary>
        /// 转化成本地时间的时间戳(s)
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static long ToLocalSeconds(this DateTime dt)
        {

            return new DateTimeOffset(dt).ToUnixTimeSeconds();
        }

        /// <summary>
        /// 转化成本地的时间戳(ms)
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static long ToLocalMilliseconds(this DateTime dt)
        {

            return new DateTimeOffset(dt).ToUnixTimeMilliseconds();
        }

        /// <summary>
        /// 秒数转化成时间
        /// </summary>
        /// <param name="seconds"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromSeconds(this long seconds)
        {
            //计算自己的时区
            var dto = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
            return dto.DateTime.AddHours(TimeZoneInfo.Local.BaseUtcOffset.Hours);
        }

        ///// <summary>
        ///// 时间戳s转时间
        ///// </summary>
        ///// <param name="timestamp">s</param>
        ///// <returns></returns>
        //public static DateTime ToDateTime(this long timestamp)
        //{

        //    var date = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Local);
        //    return date.AddSeconds(timestamp);
        //}

        /// <summary>
        /// 时间戳ms转时间
        /// </summary>
        /// <param name="timestamp">ms</param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromMilliseconds(this long timestamp)
        {

            var date = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Local);
            return date.AddMilliseconds(timestamp).AddHours(TimeZoneInfo.Local.BaseUtcOffset.Hours);
        }

        /// <summary>
        /// 转化成小写的md5
        /// </summary>
        /// <param name="inputValue"></param>
        /// <returns></returns>
        public static string ToMd5Lower(this string inputValue)
        {

            using (var md5 = System.Security.Cryptography.MD5.Create())
            {
                var result = md5.ComputeHash(Encoding.UTF8.GetBytes(inputValue));
                var strResult = BitConverter.ToString(result);
                return strResult.Replace("-", "").ToLower();
            }

        }

        /// <summary>
        /// 构建密钥
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="time"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string BuildToken(this int userid,long time,string secret)
        {
            var _temp = $"{time}_{userid}_{secret}";
            return $"{time}_{userid}_{_temp}".ToMd5Lower();
        }

        /// <summary>
        /// 构建密钥
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string BuildToken(this int userid, string secret)
        {
            var time = DateTime.Now.ToUnixTimeSeconds();
            var _temp = $"{time}_{userid}_{secret}".ToMd5Lower();
            return $"{time}_{userid}_{_temp}";
        }

        /// <summary>
        /// 检查密钥
        /// </summary>
        /// <param name="token"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static bool CheckToken(this string token,string secret)
        {
            if (!String.IsNullOrEmpty(token))
            {
                var strs = token.Split('_');
                if (strs.Length >= 3)
                {
                    if ($"{strs[0]}_{strs[1]}_{secret}".ToMd5Lower() == strs[2])
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        ///// <summary>
        /////  AES 加密
        ///// </summary>
        ///// <param name="str">明文（待加密）</param>
        ///// <param name="key">密文</param>
        ///// <returns></returns>
        //public static string AesEncrypt(string str, string key)
        //{
        //    if (string.IsNullOrEmpty(str)) return null;
        //    Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);

        //    System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
        //    {
        //        Key = Encoding.UTF8.GetBytes(key),
        //        Mode = System.Security.Cryptography.CipherMode.ECB,
        //        Padding = System.Security.Cryptography.PaddingMode.PKCS7
        //    };

        //    System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateEncryptor();
        //    Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        //    return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        //}
        ///// <summary>
        /////  AES 解密
        ///// </summary>
        ///// <param name="str">明文（待解密）</param>
        ///// <param name="key">密文</param>
        ///// <returns></returns>
        //public static string AesDecrypt(string str, string key)
        //{
        //    if (string.IsNullOrEmpty(str)) return null;
        //    Byte[] toEncryptArray = Convert.FromBase64String(str);

        //    System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
        //    {
        //        Key = Encoding.UTF8.GetBytes(key),
        //        Mode = System.Security.Cryptography.CipherMode.ECB,
        //        Padding = System.Security.Cryptography.PaddingMode.PKCS7
        //    };

        //    System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateDecryptor();
        //    Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        //    return Encoding.UTF8.GetString(resultArray);
        //}



        /// <summary>
        /// 把字符串拆分成行
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static List<string> SplitByLine(this string text)
        {
            List<string> lines = new List<string>();
            byte[] array = Encoding.UTF8.GetBytes(text);
            using (System.IO.MemoryStream stream = new System.IO.MemoryStream(array))
            {
                using (var sr = new System.IO.StreamReader(stream))
                {
                    string line = String.Empty;
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();
                        if (!String.IsNullOrEmpty(line))
                        {
                            lines.Add(line);
                        }
                    };
                }
            }
            return lines;
        }

        /// <summary>
        /// Reject The Number Char From String By Regex
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string RejectNumChar(this string str)
        {
            if (!String.IsNullOrEmpty(str))
            {
                return System.Text.RegularExpressions.Regex.Replace(str, "[0-9]", "");
            }
            else
            {
                return str;
            }
        }

        /// <summary>
        /// 转化成base64
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string ToBase64Encode(this string content)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(content);
            return Convert.ToBase64String(bytes);
        }


        /// <summary>
        /// 构建访客Token
        /// </summary>
        /// <param name="uid">访客ID</param>
        /// <param name="second">时间戳</param>
        /// <param name="appid">站点ID</param>
        /// <returns></returns>
        public static string BuildVisitorToken(this int uid, long second, int appid)
        {
            var newtime = second - 123456789 + uid;
            var token = $"{uid}_{newtime}".ToMd5Lower();
            return $"{uid}_{second}_{token}_{appid}";
        }

        /// <summary>
        /// 检查访客密钥
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool CheckVisitorToken(this string token)
        {
            if (token.IndexOf("_") > 0)
            {
                var items = token.Split('_');
                if (items.Length >= 3)
                {
                    int.TryParse(items[0], out int uid);
                    long.TryParse(items[1], out long utime);
                    if (uid > 0 && utime > 0)
                    {
                        var newt = utime - 123456789 + uid;
                        if ($"{uid}_{newt}".ToMd5Lower() == items[2])
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }
    }




    /// <summary>
    /// 
    /// </summary>
    public class PublicString
    {
        ///// <summary>
        ///// 节点运行数 cache:node:{node.id} 节点运行报表 felid:timeformat
        ///// </summary>
        //public const string CacheNodeTask = "cache:node:{0}";

        /// <summary>
        /// 总运行数 cache:task:run:{0}
        /// </summary>
        public const string CacheTaskRun = "cache:task:run:{0}";

        /// <summary>
        /// 成功运行数 cache:task:success:{0}
        /// </summary>
        public const string CacheTaskSuccess = "cache:task:success:{0}";

        /// <summary>
        /// 失败运行数 cache:task:faild:{0}
        /// </summary>
        public const string CacheTaskFailed = "cache:task:faild:{0}";

        ///// <summary>
        ///// 
        ///// </summary>
        //public const string TokenKey = "5c33688ac5ac4459d5399149549014b8";


        /// <summary>
        /// time:taskid:run/err/fai
        /// </summary>
        public const string CollectFieldFormat = "{0}:{1}:{2}";

        /// <summary>
        /// 统计数据的根Key
        /// </summary>
        public const string CollectHashKey = "collect:report";

        /// <summary>
        /// 统计数据的小时报表
        /// </summary>
        public const string CollectHourHashKey = "collect:report:hour";

        /// <summary>
        /// 数据统计的日报表
        /// </summary>
        public const string CollectDailyHashKey = "collect:report:daily";

        /// <summary>
        /// 数据统计的月报表
        /// </summary>
        public const string CollectMonthHashKey = "collect:report:month";

        /// <summary>
        /// 图形验证码缓存{guid}16位
        /// </summary>
        public const string CacheImageHead = "cache:image:code:{0}";

        /// <summary>
        /// cache:grade:{grade.id}
        /// </summary>
        public const string CacheGradeRole = "cache:grade:{0}";

        /// <summary>
        /// 节点通讯密钥 cache:node:token:{node.id}
        /// </summary>
        public const string CacheNodeTokenHead = "cache:node:token:{0}";


        /// <summary>
        /// RevicerInfoDto.item cache:itemdto:revicer:{revicerinfo.id}
        /// </summary>
        public const string CacheItemRevicer = "cache:itemdto:revicer:{0}";

        /// <summary>
        /// MessageInfoDto.item cache:itemdto:message:{messageinfo.code}
        /// </summary>
        public const string CacheItemMessage = "cache:itemdto:message:{0}";

        /// <summary>
        /// List RevicerInfoList
        /// </summary>
        public const string CacheListRevicer = "cache:list:revicer";

        /// <summary>
        /// slaveinfo.id
        /// </summary>
        public const string CacheItemSlaveInfo = "cache:item:slave:{0}";
    }


}
